/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.xuexiang.xuidemo.util;

import com.xuexiang.xuidemo.view.SlidingRootNavLayout;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.ComponentParent;
import ohos.agp.components.LayoutScatter;

public class SlidingRootNavBuilder {
    private static final float DEFAULT_END_SCALE = 0.65f;
    private static final int DEFAULT_DRAG_DIST_DP = 200;
    private static final int DEFAULT_SLIDE_TIME = 150;      //单位为毫秒

    private Ability ability;
    private int menuLayoutRes;
    private Component menuComponent;
    private ComponentContainer contentView;
    private Component arbitrarilyComponent;

    private boolean isMenuLocked;
    private Intent savedState;
    private boolean isMenuOpened;
    private boolean isContentClickableWhenMenuOpened;
    private int dragDistance;
    private float layoutScale;
    private int layoutElevation;

    public SlidingRootNavBuilder(Ability ability) {
        this.ability = ability;
        this.dragDistance = dpToPx(DEFAULT_DRAG_DIST_DP);
        this.isContentClickableWhenMenuOpened = true;
        this.layoutScale = DEFAULT_END_SCALE;
    }

    public SlidingRootNav inject() {
        ComponentContainer contentView = getContentView();

        Component oldRoot = contentView.getComponentAt(0);
        contentView.removeAllComponents();

        SlidingRootNavLayout newRoot = createAndInitNewRoot(oldRoot);
        Component menu = getMenuViewFor(newRoot);

        newRoot.addComponent(menu);
        newRoot.addComponent(oldRoot);

        contentView.addComponent(newRoot);
        newRoot.setSlideTime(DEFAULT_SLIDE_TIME);

        if (savedState == null && isMenuOpened) {
            newRoot.openMenu(false);
        }
        newRoot.setLayoutConfig();
        return newRoot;
    }

    public SlidingRootNavBuilder withMenuView(Component component) {
        menuComponent = component;
        return this;
    }

    public SlidingRootNavBuilder withMenuLayout(int layout) {
        menuLayoutRes = layout;
        return this;
    }

    private Component getMenuViewFor(SlidingRootNavLayout parent) {
        if (menuComponent == null) {
            if (menuLayoutRes == 0) {
                throw new IllegalStateException("No view for menu provided. You must either call .withMenuView(View) or pass a valid resource id to .withMenuLayout(int)");
            }
            menuComponent = LayoutScatter.getInstance(ability).parse(menuLayoutRes, parent, false);
        }
        return menuComponent;
    }

    private ComponentContainer getContentView() {
        if (contentView == null) {
            ComponentParent componentParent = arbitrarilyComponent.getComponentParent();
            while (true) {
                ComponentParent tmp = componentParent.getComponentParent();
                if (tmp == null) break;
                else componentParent = tmp;
            }
            contentView = (ComponentContainer) componentParent;
        }
        return contentView;
    }

    private SlidingRootNavLayout createAndInitNewRoot(Component oldRoot) {
        SlidingRootNavLayout newRoot = new SlidingRootNavLayout(ability);
//        newRoot.setId(R.id.srn_root_layout);
//        newRoot.setMaxDragDistance(dragDistance);
//        newRoot.setGravity(gravity);
        newRoot.setRootView(oldRoot);
        newRoot.setHeight(-1);
        newRoot.setWidth(-1);
        newRoot.setMenuLocked(isMenuLocked);
        newRoot.setContentClickableWhenMenuOpened(isContentClickableWhenMenuOpened);
        newRoot.setMaxDragDistance(dragDistance);
        newRoot.setLayoutScale(layoutScale);
        newRoot.setLayoutElevation(layoutElevation);
        return newRoot;
    }

    //增加Ability中任意一个Component
    public SlidingRootNavBuilder withArbitrarilyView(Component component) {
        arbitrarilyComponent = component;
        return this;
    }

    public SlidingRootNavBuilder withContentView(ComponentContainer cv) {
        contentView = cv;
        return this;
    }

    public SlidingRootNavBuilder withMenuLocked(boolean locked) {
        isMenuLocked = locked;
        return this;
    }

    public SlidingRootNavBuilder withSavedState(Intent state) {
        savedState = state;
        return this;
    }

    public SlidingRootNavBuilder withMenuOpened(boolean opened) {
        isMenuOpened = opened;
        return this;
    }

    public SlidingRootNavBuilder withContentClickableWhenMenuOpened(boolean clickable) {
        isContentClickableWhenMenuOpened = clickable;
        return this;
    }

    public SlidingRootNavBuilder withDragDistance(int dp) {
        return withDragDistancePx(dpToPx(dp));
    }

    public SlidingRootNavBuilder withDragDistancePx(int px) {
        dragDistance = px;
        return this;
    }

    public SlidingRootNavBuilder withRootViewScale(float scale) {
        layoutScale = scale;
        return this;
    }

    public SlidingRootNavBuilder withRootViewElevation(int elevation) {
        return withRootViewElevationPx(dpToPx(elevation));
    }

    public SlidingRootNavBuilder withRootViewElevationPx(int elevation) {
        layoutElevation = elevation;
        return this;
    }

    private int dpToPx(int dp) {
        return Math.round(AttrHelper.getDensity(ability) * dp);
    }
}
